#ifndef     __PROTO_H
#define     __PROTO_H

#include "../utils/error.h"
#include <string.h>
#include "../serialize/encode.h"
#include "../utils/alg.h"

namespace conn {

namespace cmd {

constexpr uint8_t STATUS = 0x00;
constexpr uint8_t LOG = 0x01;
constexpr uint8_t OTA_START = 0x02;
constexpr uint8_t OTA_TRANSLATE = 0x03;
constexpr uint8_t OTA_COMPAT = 0x04;

}

namespace type {

constexpr uint8_t ACK = 0x00;
constexpr uint8_t PING = 0x01;
constexpr uint8_t PONG = 0x02;
constexpr uint8_t SIMPLE_REQ = 0x03;
constexpr uint8_t SIMPLE_RES = 0x04;
constexpr uint8_t SESSION = 0x05;
constexpr uint8_t REQ = 0x06;
constexpr uint8_t RES = 0x07;
constexpr uint8_t NOTIFY = 0x08;
constexpr uint8_t NOTIFY_ACK = 0x09;

}

namespace frame {

constexpr uint8_t HEAD0 = 0xE1;
constexpr uint8_t HEAD1 = 0x1E;
constexpr uint16_t HEAD = 0xE11E;
constexpr uint8_t END = 0xEF;

}

template <typename... Ts>
uint8_t make(uint8_t *buf, uint8_t type, uint8_t seq, const Ts&... ts) {
    using namespace serialize;
    
    buf[0] = frame::HEAD0;
    buf[1] = frame::HEAD1;
    //buf[2] = 0;
    uint8_t n = encode_all(buf + 3, type, seq, ts...);
    buf[2] = 5 + n;
    uint8_t s = utils::alg::xor_sum(buf + 3, n);
    buf[3 + n] = s;
    buf[4 + n] = frame::END;

    return n + 5;
} 



}

#endif
